package com.zl.learning.io.nio.Chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.util.Iterator;

/**
 * Created by zhaolei on 2017/5/2.
 */
public class DatagramChannelClientDemo {
    private static final String serverIp = "127.0.0.1";
    private static final int port = 9975;

    private DatagramChannel channel;
    private Charset charset = Charset.forName("UTF-8");
    private Selector selector = null;

    public DatagramChannelClientDemo() throws IOException{
        try {
            selector = Selector.open();
            channel = DatagramChannel.open();
        } catch (IOException e) {
            e.printStackTrace();
            selector = null;
            channel = null;
            System.out.println("超时");
        }
    }

    public ByteBuffer encode(String str){
        return charset.encode(str);
    }

    public String decode(ByteBuffer bb){
        return charset.decode(bb).toString();
    }

    public void service() throws IOException {
        if(channel == null || selector == null) return;
        channel.configureBlocking(false);
        channel.connect(new InetSocketAddress(serverIp,port));
        channel.write(ByteBuffer.wrap("客户商请求获取消息".getBytes()));
        channel.register(selector, SelectionKey.OP_READ);
        while (selector.select()>0){
            Iterator iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey key = null;
                try {
                    key = (SelectionKey) iterator.next();
                    iterator.remove();
                    if(key.isReadable()){
                        reveice(key);
                    }
                    if(key.isWritable()){
                        //send(key);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    try {
                        if(key!=null){
                            key.cancel();
                            key.channel().close();
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

    private synchronized void reveice(SelectionKey key) throws IOException {
        String threadName = Thread.currentThread().getName();
        if(key == null) return;
        try {
            DatagramChannel sc = (DatagramChannel) key.channel();
            StringBuilder content = new StringBuilder();
            ByteBuffer buf = ByteBuffer.allocate(65507);
            buf.clear();
            SocketAddress address = sc.receive(buf);
            String clientAddress = address.toString().replace("/","").split(":")[0];
            String clientPost = address.toString().replace("/","").split(":")[1];
            System.out.println(threadName+"\t"+address.toString());
            buf.flip();
            while (buf.hasRemaining()){
                buf.get(new byte[buf.limit()]);
                byte[] tmp = buf.array();
                content.append(new String(tmp));
            }
            buf.clear();
            System.out.println(threadName+"接收："+ content.toString().trim());
            content = new StringBuilder();
            ByteBuffer buf2 = ByteBuffer.allocate(65507);
            buf2.clear();
            SocketAddress address2 = sc.receive(buf2);
            buf2.flip();
            while (buf2.hasRemaining()){
                buf2.get(new byte[buf2.limit()]);
                byte[] tmp = buf2.array();
                content.append(new String(tmp));
            }
            buf2.clear();
            System.out.println(threadName+"接收2:"+ content.toString().trim());
        } catch (IOException e) {
            System.out.println(threadName+"服务端口未找到！");
            e.printStackTrace();
        }
        send(2);
    }

    private boolean flag = false;

    private void send(int i) throws IOException {
        if(flag) return;
        ByteBuffer buf2 = ByteBuffer.allocate(48);
        buf2.clear();
        buf2.put(("客户端请求获取消息（第" + i + "次)").getBytes());
        buf2.flip();
        channel.write(buf2);
        channel.register(selector,SelectionKey.OP_READ);
    }

    public static void main(String[] args) {
        try {
            new DatagramChannelClientDemo().service();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

